<!DOCTYPE html><html class=split lang=en-US-x-hixie><script src=../link-fixup.js defer=""></script>
<!-- Mirrored from html.spec.whatwg.org/dev/web-messaging.html by HTTrack Website Copier/3.x [XR&CO'2014], Wed, 10 Sep 2025 08:36:28 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=utf-8" /><!-- /Added by HTTrack -->
<meta charset=utf-8><meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name=viewport><title>HTML Standard, Edition for Web Developers</title><meta content=#3c790a name=theme-color><meta content="light dark" name=color-scheme><link rel=stylesheet href=../../resources.whatwg.org/standard-shared-with-dev.css crossorigin=""><link rel=icon href=https://resources.whatwg.org/logo.svg crossorigin=""><link rel=stylesheet href=styles.css crossorigin=""><script>
   function toggleStatus(div) {
     div.parentNode.classList.toggle('wrapped');
   }
   function setLinkFragment(link) {
     link.hash = location.hash;
   }
  </script><body>
  <script async="" src=search.js></script>
  
  
  <header id=head class="head with-buttons">
   <a href=https://whatwg.org/ class=logo><img width=100 alt=WHATWG crossorigin="" class=darkmode-aware src=https://resources.whatwg.org/logo.svg height=100></a>
   
   <hgroup><h1><a rel=home href=index.html>HTML: The Living Standard</a></h1><p id=dev-edition-h2>Edition for Web Developers — Last Updated <span class=pubdate>10 September 2025</span></hgroup>
   

   <div id=search>
    <input placeholder="Search. Press '/'" autocomplete=off name=query id=query type=search>
    <ol id=results></ol>
   </div>
  </header>

  

  

  

  
  

  
  

  

  <nav><a href=server-sent-events.html>← 9.2 Server-sent events</a> — <a href=index.html>Table of Contents</a> — <a href=workers.html>10 Web workers →</a></nav><ol class=toc><li><ol><li><a href=web-messaging.html#web-messaging><span class=secno>9.3</span> Cross-document messaging</a><ol><li><a href=web-messaging.html#introduction-11><span class=secno>9.3.1</span> Introduction</a><li><a href=web-messaging.html#security-postmsg><span class=secno>9.3.2</span> Security</a><li><a href=web-messaging.html#posting-messages><span class=secno>9.3.3</span> Posting messages</a></ol><li><a href=web-messaging.html#channel-messaging><span class=secno>9.4</span> Channel messaging</a><ol><li><a href=web-messaging.html#introduction-12><span class=secno>9.4.1</span> Introduction</a><ol><li><a href=web-messaging.html#examples-5><span class=secno>9.4.1.1</span> Examples</a><li><a href=web-messaging.html#ports-as-the-basis-of-an-object-capability-model-on-the-web><span class=secno>9.4.1.2</span> Ports as the basis of an object-capability model on the web</a><li><a href=web-messaging.html#ports-as-the-basis-of-abstracting-out-service-implementations><span class=secno>9.4.1.3</span> Ports as the basis of abstracting out service implementations</a></ol><li><a href=web-messaging.html#message-channels><span class=secno>9.4.2</span> Message channels</a><li><a href=web-messaging.html#properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope><span class=secno>9.4.3</span> Properties present on <code>MessagePort</code>, <code>Worker</code>, and
  <code>DedicatedWorkerGlobalScope</code></a><li><a href=web-messaging.html#message-ports><span class=secno>9.4.4</span> Message ports</a><li><a href=web-messaging.html#ports-and-garbage-collection><span class=secno>9.4.5</span> Ports and garbage collection</a></ol><li><a href=web-messaging.html#broadcasting-to-other-browsing-contexts><span class=secno>9.5</span> Broadcasting to other browsing contexts</a></ol></ol><h3 id=web-messaging><span class=secno>9.3</span> <dfn id=crossDocumentMessages>Cross-document messaging</dfn><a href=#web-messaging class=self-link></a></h3><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage title="The window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.">Window/postMessage</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>3+</span></span><span class="safari yes"><span>Safari</span><span>4+</span></span><span class="chrome yes"><span>Chrome</span><span>2+</span></span><hr><span class="opera yes"><span>Opera</span><span>9.5+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>10+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android yes"><span>WebView Android</span><span>≤37+</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div>

  <p>Web browsers, for security and privacy reasons, prevent documents in different domains from
  affecting each other; that is, cross-site scripting is disallowed.</p>

  <p>While this is an important security feature, it prevents pages from different domains from
  communicating even when those pages are not hostile. This section introduces a messaging system
  that allows documents to communicate with each other regardless of their source domain, in a way
  designed to not enable cross-site scripting attacks.</p>

  <p id=fingerprint-postMessage class=note><a href=#fingerprint-postMessage class=self-link></a>
  
  The <code>postMessage()</code> API can be used as a <a id=web-messaging:tracking-vector href=https://infra.spec.whatwg.org/#tracking-vector data-x-internal=tracking-vector>tracking
  vector</a>.</p>


  <h4 id=introduction-11><span class=secno>9.3.1</span> Introduction<a href=#introduction-11 class=self-link></a></h4>

  

  <div class=example>

   <p>For example, if document A contains an <code id=introduction-11:the-iframe-element><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code> element that contains document B,
   and script in document A calls <code>postMessage()</code> on the
   <code>Window</code> object of document B, then a message event will be fired on that object,
   marked as originating from the <code>Window</code> of document A. The script in document A might
   look like:</p>

   <pre><code class='js'><c- a>var</c-> o <c- o>=</c-> document<c- p>.</c->getElementsByTagName<c- p>(</c-><c- t>&apos;iframe&apos;</c-><c- p>)[</c-><c- mf>0</c-><c- p>];</c->
o<c- p>.</c->contentWindow<c- p>.</c->postMessage<c- p>(</c-><c- t>&apos;Hello world&apos;</c-><c- p>,</c-> <c- t>&apos;https://b.example.org/&apos;</c-><c- p>);</c-></code></pre>

   <p>To register an event handler for incoming events, the script would use <code>addEventListener()</code> (or similar mechanisms). For example, the script in document B
   might look like:</p>

   <pre><code class='js'>window<c- p>.</c->addEventListener<c- p>(</c-><c- t>&apos;message&apos;</c-><c- p>,</c-> receiver<c- p>,</c-> <c- kc>false</c-><c- p>);</c->
<c- a>function</c-> receiver<c- p>(</c->e<c- p>)</c-> <c- p>{</c->
  <c- k>if</c-> <c- p>(</c->e<c- p>.</c->origin <c- o>==</c-> <c- t>&apos;https://example.com&apos;</c-><c- p>)</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c->e<c- p>.</c->data <c- o>==</c-> <c- t>&apos;Hello world&apos;</c-><c- p>)</c-> <c- p>{</c->
      e<c- p>.</c->source<c- p>.</c->postMessage<c- p>(</c-><c- t>&apos;Hello&apos;</c-><c- p>,</c-> e<c- p>.</c->origin<c- p>);</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
      alert<c- p>(</c->e<c- p>.</c->data<c- p>);</c->
    <c- p>}</c->
  <c- p>}</c->
<c- p>}</c-></code></pre>

   <p>This script first checks the domain is the expected domain, and then looks at the message,
   which it either displays to the user, or responds to by sending a message back to the document
   which sent the message in the first place.</p>

  </div>


  <h4 id=security-postmsg><span class=secno>9.3.2</span> Security<a href=#security-postmsg class=self-link></a></h4>

  

  <p id=security-4 class=warning>Use of this API requires extra care to protect users from
  hostile entities abusing a site for their own purposes.</p>

  <p>Authors should check the <code id=security-postmsg:dom-messageevent-origin><a href=comms.html#dom-messageevent-origin>origin</a></code> attribute to
  ensure that messages are only accepted from domains that they expect to receive messages from.
  Otherwise, bugs in the author's message handling code could be exploited by hostile sites.</p>

  <p>Furthermore, even after checking the <code id=security-postmsg:dom-messageevent-origin-2><a href=comms.html#dom-messageevent-origin>origin</a></code>
  attribute, authors should also check that the data in question is of the expected format.
  Otherwise, if the source of the event has been attacked using a cross-site scripting flaw, further
  unchecked processing of information sent using the <code>postMessage()</code> method could result in the attack being
  propagated into the receiver.</p>

  <p>Authors should not use the wildcard keyword (*) in the <var>targetOrigin</var>
  argument in messages that contain any confidential information, as otherwise there is no way to
  guarantee that the message is only delivered to the recipient to which it was intended.</p>

  <hr>

  <p>Authors who accept messages from any origin are encouraged to consider the risks of a
  denial-of-service attack. An attacker could send a high volume of messages; if the receiving page
  performs expensive computation or causes network traffic to be sent for each such message, the
  attacker's message could be multiplied into a denial-of-service attack. Authors are encouraged to
  employ rate limiting (only accepting a certain number of messages per minute) to make such attacks
  impractical.</p>


  



  <h4 id=posting-messages><span class=secno>9.3.3</span> Posting messages<a href=#posting-messages class=self-link></a></h4>

  <dl class=domintro><dt><code><var>window</var>.<span id=dom-window-postmessage-options>postMessage</span>(<var>message</var> [, <var>options</var> ])</code><dd>
    <p>Posts a message to the given window. Messages can be structured objects, e.g. nested objects
    and arrays, can contain JavaScript values (strings, numbers, <code id=posting-messages:date><a data-x-internal=date href=https://tc39.es/ecma262/#sec-date-objects>Date</a></code> objects, etc.),
    and can contain certain data objects such as <code id=posting-messages:file><a data-x-internal=file href=https://w3c.github.io/FileAPI/#dfn-file>File</a></code> <code id=posting-messages:blob><a data-x-internal=blob href=https://w3c.github.io/FileAPI/#dfn-Blob>Blob</a></code>,
    <code id=posting-messages:filelist><a data-x-internal=filelist href=https://w3c.github.io/FileAPI/#filelist-section>FileList</a></code>, and <code id=posting-messages:idl-arraybuffer><a data-x-internal=idl-arraybuffer href=https://webidl.spec.whatwg.org/#idl-ArrayBuffer>ArrayBuffer</a></code> objects.</p>

    <p>Objects listed in the <code>transfer</code> member
    of <var>options</var> are transferred, not just cloned, meaning that they are no longer usable
    on the sending side.</p>

    <p>A target origin can be specified using the <code>targetOrigin</code> member of
    <var>options</var>. If not provided, it defaults to "<code>/</code>". This default
    restricts the message to same-origin targets only.</p>

    <p>If the origin of the target window doesn't match the given target origin, the message is
    discarded, to avoid information leakage. To send the message to the target regardless of origin,
    set the target origin to "<code>*</code>".</p>

    <p>Throws a <a id=posting-messages:datacloneerror href=https://webidl.spec.whatwg.org/#datacloneerror data-x-internal=datacloneerror>"<code>DataCloneError</code>"</a> <code id=posting-messages:domexception><a data-x-internal=domexception href=https://webidl.spec.whatwg.org/#dfn-DOMException>DOMException</a></code> if
    <var>transfer</var> array contains duplicate objects or if <var>message</var> could not be
    cloned.</p>
   <dt><code><var>window</var>.<span>postMessage</span>(<var>message</var>, <var>targetOrigin</var> [, <var>transfer</var> ])</code><dd><p>This is an alternate version of <code id=posting-messages:dom-window-postmessage-options><a href=#dom-window-postmessage-options>postMessage()</a></code> where the target origin is specified
   as a parameter. Calling <code>window.postMessage(message, target, transfer)</code> is
   equivalent to <code>window.postMessage(message, {targetOrigin,
   transfer})</code>.</dl>

  <p class=note>When posting a message to a <code>Window</code> of a <a id=posting-messages:browsing-context href=document-sequences.html#browsing-context>browsing context</a>
  that has just been navigated to a new <code>Document</code> is likely to result in the message not
  receiving its intended recipient: the scripts in the target <a id=posting-messages:browsing-context-2 href=document-sequences.html#browsing-context>browsing context</a> have to
  have had time to set up listeners for the messages. Thus, for instance, in situations where a
  message is to be sent to the <code>Window</code> of newly created child <code id=posting-messages:the-iframe-element><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code>,
  authors are advised to have the child <code>Document</code> post a message to their parent
  announcing their readiness to receive messages, and for the parent to wait for this message before
  beginning posting messages.</p>

  




  <h3 id=channel-messaging><span class=secno>9.4</span> <dfn>Channel messaging</dfn><a href=#channel-messaging class=self-link></a></h3><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API title="The Channel Messaging API allows two separate scripts running in different browsing contexts attached to the same document (e.g., two IFrames, or the main document and an IFrame, two documents via a SharedWorker, or two workers) to communicate directly, passing messages between one another through two-way channels (or pipes) with a port at each end.">Channel_Messaging_API</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>41+</span></span><span class="safari yes"><span>Safari</span><span>5+</span></span><span class="chrome yes"><span>Chrome</span><span>2+</span></span><hr><span class="opera yes"><span>Opera</span><span>10.6+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>10+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>11+</span></span></div></div><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging title="The Channel Messaging API allows two separate scripts running in different browsing contexts attached to the same document (e.g., two <iframe> elements, the main document and a single <iframe>, or two documents via a SharedWorker) to communicate directly, passing messages between each other through two-way channels (or pipes) with a port at each end.">Channel_Messaging_API/Using_channel_messaging</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>41+</span></span><span class="safari yes"><span>Safari</span><span>5+</span></span><span class="chrome yes"><span>Chrome</span><span>2+</span></span><hr><span class="opera yes"><span>Opera</span><span>10.6+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>10+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>11+</span></span></div></div></div>

  <h4 id=introduction-12><span class=secno>9.4.1</span> Introduction<a href=#introduction-12 class=self-link></a></h4>

  

  <p>To enable independent pieces of code (e.g. running in different <a href=document-sequences.html#browsing-context id=introduction-12:browsing-context>browsing contexts</a>) to communicate directly, authors can use <a href=#channel-messaging id=introduction-12:channel-messaging>channel
  messaging</a>.</p>

  <p>Communication channels in this mechanism are implemented as two-ways pipes, with a port at each
  end. Messages sent in one port are delivered at the other port, and vice-versa. Messages are
  delivered as DOM events, without interrupting or blocking running <span>tasks</span>.</p>

  <p>To create a connection (two "entangled" ports), the <code>MessageChannel()</code>
  constructor is called:</p>

  <pre><code class='js'><c- a>var</c-> channel <c- o>=</c-> <c- k>new</c-> MessageChannel<c- p>();</c-></code></pre>

  <p>One of the ports is kept as the local port, and the other port is sent to the remote code, e.g.
  using <code>postMessage()</code>:</p>

  <pre><code class='js'>otherWindow<c- p>.</c->postMessage<c- p>(</c-><c- t>&apos;hello&apos;</c-><c- p>,</c-> <c- t>&apos;https://example.com&apos;</c-><c- p>,</c-> <c- p>[</c->channel<c- p>.</c->port2<c- p>]);</c-></code></pre>

  <p>To send messages, the <code id=introduction-12:dom-messageport-postmessage><a href=#dom-messageport-postmessage>postMessage()</a></code> method on
  the port is used:</p>

  <pre><code class='js'>channel<c- p>.</c->port1<c- p>.</c->postMessage<c- p>(</c-><c- t>&apos;hello&apos;</c-><c- p>);</c-></code></pre>

  <p>To receive messages, one listens to <code id=introduction-12:event-message><a href=indices.html#event-message>message</a></code> events:</p>

  <pre><code class='js'>channel<c- p>.</c->port1<c- p>.</c->onmessage <c- o>=</c-> handleMessage<c- p>;</c->
<c- a>function</c-> handleMessage<c- p>(</c->event<c- p>)</c-> <c- p>{</c->
  <c- c1>// message is in event.data</c->
  <c- c1>// ...</c->
<c- p>}</c-></code></pre>

  <p>Data sent on a port can be structured data; for example here an array of strings is passed on a
  <code>MessagePort</code>:</p>

  <pre><code class='js'>port1<c- p>.</c->postMessage<c- p>([</c-><c- t>&apos;hello&apos;</c-><c- p>,</c-> <c- t>&apos;world&apos;</c-><c- p>]);</c-></code></pre>


  <h5 id=examples-5><span class=secno>9.4.1.1</span> Examples<a href=#examples-5 class=self-link></a></h5>

  

  <div class=example>

   <p>In this example, two JavaScript libraries are connected to each other using
   <code>MessagePort</code>s. This allows the libraries to later be hosted in different frames, or
   in <code id=examples-5:worker><a href=workers.html#worker>Worker</a></code> objects, without any change to the APIs.</p>

   <pre><code class='html'><c- p>&lt;</c-><c- f>script</c-> <c- e>src</c-><c- o>=</c-><c- s>&quot;contacts.js&quot;</c-><c- p>&gt;&lt;/</c-><c- f>script</c-><c- p>&gt;</c-> <c- c>&lt;!-- exposes a contacts object --&gt;</c->
<c- p>&lt;</c-><c- f>script</c-> <c- e>src</c-><c- o>=</c-><c- s>&quot;compose-mail.js&quot;</c-><c- p>&gt;&lt;/</c-><c- f>script</c-><c- p>&gt;</c-> <c- c>&lt;!-- exposes a composer object --&gt;</c->
<c- p>&lt;</c-><c- f>script</c-><c- p>&gt;</c->
 <c- a>var</c-> channel <c- o>=</c-> <c- k>new</c-> MessageChannel<c- p>();</c->
 composer<c- p>.</c->addContactsProvider<c- p>(</c->channel<c- p>.</c->port1<c- p>);</c->
 contacts<c- p>.</c->registerConsumer<c- p>(</c->channel<c- p>.</c->port2<c- p>);</c->
<c- p>&lt;/</c-><c- f>script</c-><c- p>&gt;</c-></code></pre>

   <p>Here's what the "addContactsProvider()" function's implementation could look like:</p>

   <pre><code class='js'><c- a>function</c-> addContactsProvider<c- p>(</c->port<c- p>)</c-> <c- p>{</c->
  port<c- p>.</c->onmessage <c- o>=</c-> <c- a>function</c-> <c- p>(</c->event<c- p>)</c-> <c- p>{</c->
    <c- k>switch</c-> <c- p>(</c->event<c- p>.</c->data<c- p>.</c->messageType<c- p>)</c-> <c- p>{</c->
      <c- k>case</c-> <c- t>&apos;search-result&apos;</c-><c- o>:</c-> handleSearchResult<c- p>(</c->event<c- p>.</c->data<c- p>.</c->results<c- p>);</c-> <c- k>break</c-><c- p>;</c->
      <c- k>case</c-> <c- t>&apos;search-done&apos;</c-><c- o>:</c-> handleSearchDone<c- p>();</c-> <c- k>break</c-><c- p>;</c->
      <c- k>case</c-> <c- t>&apos;search-error&apos;</c-><c- o>:</c-> handleSearchError<c- p>(</c->event<c- p>.</c->data<c- p>.</c->message<c- p>);</c-> <c- k>break</c-><c- p>;</c->
      <c- c1>// ...</c->
    <c- p>}</c->
  <c- p>};</c->
<c- p>};</c-></code></pre>

   <p>Alternatively, it could be implemented as follows:</p>

   <pre><code class='js'><c- a>function</c-> addContactsProvider<c- p>(</c->port<c- p>)</c-> <c- p>{</c->
  port<c- p>.</c->addEventListener<c- p>(</c-><c- t>&apos;message&apos;</c-><c- p>,</c-> <c- a>function</c-> <c- p>(</c->event<c- p>)</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c->event<c- p>.</c->data<c- p>.</c->messageType <c- o>==</c-> <c- t>&apos;search-result&apos;</c-><c- p>)</c->
      handleSearchResult<c- p>(</c->event<c- p>.</c->data<c- p>.</c->results<c- p>);</c->
  <c- p>});</c->
  port<c- p>.</c->addEventListener<c- p>(</c-><c- t>&apos;message&apos;</c-><c- p>,</c-> <c- a>function</c-> <c- p>(</c->event<c- p>)</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c->event<c- p>.</c->data<c- p>.</c->messageType <c- o>==</c-> <c- t>&apos;search-done&apos;</c-><c- p>)</c->
      handleSearchDone<c- p>();</c->
  <c- p>});</c->
  port<c- p>.</c->addEventListener<c- p>(</c-><c- t>&apos;message&apos;</c-><c- p>,</c-> <c- a>function</c-> <c- p>(</c->event<c- p>)</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c->event<c- p>.</c->data<c- p>.</c->messageType <c- o>==</c-> <c- t>&apos;search-error&apos;</c-><c- p>)</c->
      handleSearchError<c- p>(</c->event<c- p>.</c->data<c- p>.</c->message<c- p>);</c->
  <c- p>});</c->
  <c- c1>// ...</c->
  port<c- p>.</c->start<c- p>();</c->
<c- p>};</c-></code></pre>

   <p>The key difference is that when using <code id=examples-5:dom-eventtarget-addeventlistener><a data-x-internal=dom-eventtarget-addeventlistener href=https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener>addEventListener()</a></code>, the <code id=examples-5:dom-messageport-start><a href=#dom-messageport-start>start()</a></code> method must also be invoked. When using <code id=examples-5:handler-messageeventtarget-onmessage><a href=#handler-messageeventtarget-onmessage>onmessage</a></code>, the call to <code id=examples-5:dom-messageport-start-2><a href=#dom-messageport-start>start()</a></code> is implied.</p>

   <p>The <code id=examples-5:dom-messageport-start-3><a href=#dom-messageport-start>start()</a></code> method, whether called explicitly or
   implicitly (by setting <code id=examples-5:handler-messageeventtarget-onmessage-2><a href=#handler-messageeventtarget-onmessage>onmessage</a></code>),
   starts the flow of messages: messages posted on message ports are initially paused, so that they
   don't get dropped on the floor before the script has had a chance to set up its handlers.</p>

  </div>


  <h5 id=ports-as-the-basis-of-an-object-capability-model-on-the-web><span class=secno>9.4.1.2</span> Ports as the basis of an object-capability model on the web<a href=#ports-as-the-basis-of-an-object-capability-model-on-the-web class=self-link></a></h5>

  

  <p>Ports can be viewed as a way to expose limited capabilities (in the object-capability model
  sense) to other actors in the system. This can either be a weak capability system, where the ports
  are merely used as a convenient model within a particular origin, or as a strong capability model,
  where they are provided by one origin <var>provider</var> as the only mechanism by which
  another origin <var>consumer</var> can effect change in or obtain information from <var>provider</var>.</p>

  <p>For example, consider a situation in which a social web site embeds in one <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code>
  the user's email contacts provider (an address book site, from a second origin), and in a second
  <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element-2><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code> a game (from a third origin). The outer social site and the game in the second
  <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element-3><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code> cannot access anything inside the first <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element-4><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code>; together they can
  only:</p>

  <ul><li><p><a id=ports-as-the-basis-of-an-object-capability-model-on-the-web:navigate href=browsing-the-web.html#navigate>Navigate</a> the <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element-5><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code> to a new <a id=ports-as-the-basis-of-an-object-capability-model-on-the-web:url href=https://url.spec.whatwg.org/#concept-url data-x-internal=url>URL</a>, such as the same
   <a id=ports-as-the-basis-of-an-object-capability-model-on-the-web:url-2 href=https://url.spec.whatwg.org/#concept-url data-x-internal=url>URL</a> but with a different <a href=https://url.spec.whatwg.org/#concept-url-fragment id=ports-as-the-basis-of-an-object-capability-model-on-the-web:concept-url-fragment data-x-internal=concept-url-fragment>fragment</a>,
   causing the <code>Window</code> in the <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element-6><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code> to receive a <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:event-hashchange><a href=indices.html#event-hashchange>hashchange</a></code> event.<li><p>Resize the <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element-7><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code>, causing the <code>Window</code> in the <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element-8><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code>
   to receive a <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:event-resize><a data-x-internal=event-resize href=https://drafts.csswg.org/cssom-view/#eventdef-window-resize>resize</a></code> event.<li><p>Send a <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:event-message><a href=indices.html#event-message>message</a></code> event to the <code>Window</code> in the
   <code id=ports-as-the-basis-of-an-object-capability-model-on-the-web:the-iframe-element-9><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code> using the <code>window.postMessage()</code>
   API.</ul>

  <p>The contacts provider can use these methods, most particularly the third one, to provide an API
  that can be accessed by other origins to manipulate the user's address book. For example, it could
  respond to a message "<code>add-contact Guillaume Tell
  &lt;tell@pomme.example.net></code>" by adding the given person and email address to the user's
  address book.</p>

  <p>To avoid any site on the web being able to manipulate the user's contacts, the contacts
  provider might only allow certain trusted sites, such as the social site, to do this.</p>

  <p>Now suppose the game wanted to add a contact to the user's address book, and that the social
  site was willing to allow it to do so on its behalf, essentially "sharing" the trust that the
  contacts provider had with the social site. There are several ways it could do this; most simply,
  it could just proxy messages between the game site and the contacts site. However, this solution
  has a number of difficulties: it requires the social site to either completely trust the game site
  not to abuse the privilege, or it requires that the social site verify each request to make sure
  it's not a request that it doesn't want to allow (such as adding multiple contacts, reading the
  contacts, or deleting them); it also requires some additional complexity if there's ever the
  possibility of multiple games simultaneously trying to interact with the contacts provider.</p>

  <p>Using message channels and <code>MessagePort</code> objects, however, all of these problems can
  go away. When the game tells the social site that it wants to add a contact, the social site can
  ask the contacts provider not for it to add a contact, but for the <em>capability</em> to add a
  single contact. The contacts provider then creates a pair of <code>MessagePort</code> objects, and
  sends one of them back to the social site, who forwards it on to the game. The game and the
  contacts provider then have a direct connection, and the contacts provider knows to only honor a
  single "add contact" request, nothing else. In other words, the game has been granted the
  capability to add a single contact.</p>


  <h5 id=ports-as-the-basis-of-abstracting-out-service-implementations><span class=secno>9.4.1.3</span> Ports as the basis of abstracting out service implementations<a href=#ports-as-the-basis-of-abstracting-out-service-implementations class=self-link></a></h5>

  

  <p>Continuing the example from the previous section, consider the contacts provider in particular.
  While an initial implementation might have simply used <code id=ports-as-the-basis-of-abstracting-out-service-implementations:xmlhttprequest><a data-x-internal=xmlhttprequest href=https://xhr.spec.whatwg.org/#xmlhttprequest>XMLHttpRequest</a></code> objects in the
  service's <code id=ports-as-the-basis-of-abstracting-out-service-implementations:the-iframe-element><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code>, an evolution of the service might instead want to use a <a href=workers.html#sharedworker id=ports-as-the-basis-of-abstracting-out-service-implementations:sharedworker>shared worker</a> with a single <code id=ports-as-the-basis-of-abstracting-out-service-implementations:websocket-2><a data-x-internal=websocket-2 href=https://websockets.spec.whatwg.org/#websocket>WebSocket</a></code> connection.</p>

  <p>If the initial design used <code>MessagePort</code> objects to grant capabilities, or even just
  to allow multiple simultaneous independent sessions, the service implementation can switch from
  the <code id=ports-as-the-basis-of-abstracting-out-service-implementations:xmlhttprequest-2><a data-x-internal=xmlhttprequest href=https://xhr.spec.whatwg.org/#xmlhttprequest>XMLHttpRequest</a></code>s-in-each-<code id=ports-as-the-basis-of-abstracting-out-service-implementations:the-iframe-element-2><a href=iframe-embed-object.html#the-iframe-element>iframe</a></code> model to the
  shared-<code id=ports-as-the-basis-of-abstracting-out-service-implementations:websocket-2-2><a data-x-internal=websocket-2 href=https://websockets.spec.whatwg.org/#websocket>WebSocket</a></code> model without changing the API at all: the ports on the service
  provider side can all be forwarded to the shared worker without it affecting the users of the API
  in the slightest.</p>



  <h4 id=message-channels><span class=secno>9.4.2</span> Message channels<a href=#message-channels class=self-link></a></h4><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel title="The MessageChannel interface of the Channel Messaging API allows us to create a new message channel and send data through it via its two MessagePort properties.">MessageChannel</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>41+</span></span><span class="safari yes"><span>Safari</span><span>5+</span></span><span class="chrome yes"><span>Chrome</span><span>2+</span></span><hr><span class="opera yes"><span>Opera</span><span>10.6+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>10+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>11+</span></span></div></div></div>

  

  <dl class=domintro><dt><code><var>channel</var> = new <span id=dom-messagechannel>MessageChannel</span>()</code><dd>
    <p>Returns a new <code>MessageChannel</code> object with two new <code>MessagePort</code>
    objects.</p>
   <dt><code><var>channel</var>.<span id=dom-messagechannel-port1>port1</span></code><dd><p>Returns the first <code>MessagePort</code> object.<dt><code><var>channel</var>.<span id=dom-messagechannel-port2>port2</span></code><dd><p>Returns the second <code>MessagePort</code> object.</dl>

  

  
  <h4 id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope><span class=secno>9.4.3</span> Properties present on <code>MessagePort</code>, <code id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:worker><a href=workers.html#worker>Worker</a></code>, and
  <code id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:dedicatedworkerglobalscope><a href=workers.html#dedicatedworkerglobalscope>DedicatedWorkerGlobalScope</a></code><a href=#properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope class=self-link></a></h4>

  

   <p>The following are the <a id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:event-handlers href=webappapis.html#event-handlers>event handlers</a> (and their corresponding <span>event handler event types</span>)  supported,
   as <a id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:event-handler-idl-attributes href=webappapis.html#event-handler-idl-attributes>event handler IDL attributes</a>, by <span><code>MessagePort</code>,
   <code id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:worker-2><a href=workers.html#worker>Worker</a></code>, and <code id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:dedicatedworkerglobalscope-2><a href=workers.html#dedicatedworkerglobalscope>DedicatedWorkerGlobalScope</a></code> objects</span>:</p>

   <table><thead><tr><th><a href=webappapis.html#event-handlers id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:event-handlers-2>Event handler</a> <th><span>Event handler event type</span>
    <tbody><tr><td><span id=handler-messageport-onmessage></span><span id=handler-worker-onmessage></span><span id=handler-dedicatedworkerglobalscope-onmessage></span><dfn data-dfn-for=MessageEventTarget id=handler-messageeventtarget-onmessage data-dfn-type=attribute><code>onmessage</code></dfn> <div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/message_event title="The message event is fired on a MessagePort object when a message arrives on that channel.">MessagePort/message_event</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>41+</span></span><span class="safari yes"><span>Safari</span><span>5+</span></span><span class="chrome yes"><span>Chrome</span><span>2+</span></span><hr><span class="opera yes"><span>Opera</span><span>10.6+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>10+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android yes"><span>WebView Android</span><span>37+</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>11.5+</span></span></div></div><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope/message_event title="The message event is fired on a DedicatedWorkerGlobalScope object when the worker receives a message from its parent (i.e. when the parent sends a message using Worker.postMessage()).">DedicatedWorkerGlobalScope/message_event</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>3.5+</span></span><span class="safari yes"><span>Safari</span><span>4+</span></span><span class="chrome yes"><span>Chrome</span><span>4+</span></span><hr><span class="opera yes"><span>Opera</span><span>10.6+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>10+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios yes"><span>Safari iOS</span><span>5+</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android yes"><span>WebView Android</span><span>37+</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>11.5+</span></span></div></div></div><td> <code id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:event-message><a href=indices.html#event-message>message</a></code>
     <tr><td><span id=handler-messageport-onmessageerror></span><span id=handler-worker-onmessageerror></span><span id=handler-dedicatedworkerglobalscope-onmessageerror></span><dfn data-dfn-for=MessageEventTarget id=handler-messageeventtarget-onmessageerror data-dfn-type=attribute><code>onmessageerror</code></dfn> <div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/messageerror_event title="The messageerror event is fired on a MessagePort object when it receives a message that can't be deserialized.">MessagePort/messageerror_event</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>57+</span></span><span class="safari yes"><span>Safari</span><span>16.4+</span></span><span class="chrome yes"><span>Chrome</span><span>60+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>18</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>47+</span></span></div></div><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope/messageerror_event title="The messageerror event is fired on a DedicatedWorkerGlobalScope object when it receives a message that can't be deserialized.">DedicatedWorkerGlobalScope/messageerror_event</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>57+</span></span><span class="safari yes"><span>Safari</span><span>16.4+</span></span><span class="chrome yes"><span>Chrome</span><span>60+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>18</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>47+</span></span></div></div></div><td> <code id=properties-present-on-messageport,-worker,-and-dedicatedworkerglobalscope:event-messageerror><a href=indices.html#event-messageerror>messageerror</a></code>
   </table>

  <h4 id=message-ports><span class=secno>9.4.4</span> Message ports<a href=#message-ports class=self-link></a></h4><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/MessagePort title="The MessagePort interface of the Channel Messaging API represents one of the two ports of a MessageChannel, allowing messages to be sent from one port and listening out for them arriving at the other.">MessagePort</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>41+</span></span><span class="safari yes"><span>Safari</span><span>5+</span></span><span class="chrome yes"><span>Chrome</span><span>2+</span></span><hr><span class="opera yes"><span>Opera</span><span>10.6+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>10+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>11+</span></span></div></div></div>

  <p>Each channel has two message ports. Data sent through one port is received by the other port,
  and vice versa.</p>

  

  <dl class=domintro><dt><code><var>port</var>.<span id=dom-messageport-postmessage>postMessage</span>(<var>message</var> [, <var>transfer</var>])</code><dt><code><var>port</var>.<span id=dom-messageport-postmessage-options>postMessage</span>(<var>message</var> [, { <span>transfer</span> }])</code><dd>
    <p>Posts a message through the channel. Objects listed in <var>transfer</var> are transferred,
    not just cloned, meaning that they are no longer usable on the sending side.</p>

    <p>Throws a <a id=message-ports:datacloneerror href=https://webidl.spec.whatwg.org/#datacloneerror data-x-internal=datacloneerror>"<code>DataCloneError</code>"</a> <code id=message-ports:domexception><a data-x-internal=domexception href=https://webidl.spec.whatwg.org/#dfn-DOMException>DOMException</a></code> if
    <var>transfer</var> contains duplicate objects or <var>port</var>, or if <var>message</var>
    could not be cloned.</p>
   <dt><code><var>port</var>.<span id=dom-messageport-start>start</span>()</code><dd><p>Begins dispatching messages received on the port.<dt><code><var>port</var>.<span id=dom-messageport-close>close</span>()</code><dd><p>Disconnects the port, so that it is no longer active.</dl>

  


  <h4 id=ports-and-garbage-collection><span class=secno>9.4.5</span> Ports and garbage collection<a href=#ports-and-garbage-collection class=self-link></a></h4>

  

  <p class=note>Authors are strongly encouraged to explicitly close <code>MessagePort</code>
  objects to disentangle them, so that their resources can be recollected. Creating many
  <code>MessagePort</code> objects and discarding them without closing them can lead to high
  transient memory usage since garbage collection is not necessarily performed promptly, especially
  for <code>MessagePort</code>s where garbage collection can involve cross-process coordination.</p>



  <h3 id=broadcasting-to-other-browsing-contexts><span class=secno>9.5</span> <dfn>Broadcasting to other browsing contexts</dfn><a href=#broadcasting-to-other-browsing-contexts class=self-link></a></h3><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel title="The BroadcastChannel interface represents a named channel that any browsing context of a given origin can subscribe to. It allows communication between different documents (in different windows, tabs, frames or iframes) of the same origin. Messages are broadcasted via a message event fired at all BroadcastChannel objects listening to the channel, except the object that sent the message.">BroadcastChannel</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>38+</span></span><span class="safari yes"><span>Safari</span><span>15.4+</span></span><span class="chrome yes"><span>Chrome</span><span>54+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API title="The Broadcast Channel API allows basic communication between browsing contexts (that is, windows, tabs, frames, or iframes) and workers on the same origin.">Broadcast_Channel_API</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>38+</span></span><span class="safari yes"><span>Safari</span><span>15.4+</span></span><span class="chrome yes"><span>Chrome</span><span>54+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div></div>

  <p>Pages on a single <a id=broadcasting-to-other-browsing-contexts:concept-origin href=browsers.html#concept-origin>origin</a> opened by the same user in the same user agent but in
  different unrelated <a href=document-sequences.html#browsing-context id=broadcasting-to-other-browsing-contexts:browsing-context>browsing contexts</a> sometimes need to
  send notifications to each other, for example "hey, the user logged in over here, check your
  credentials again".</p>

  <p>For elaborate cases, e.g. to manage locking of shared state, to manage synchronization of
  resources between a server and multiple local clients, to share a <code id=broadcasting-to-other-browsing-contexts:websocket-2><a data-x-internal=websocket-2 href=https://websockets.spec.whatwg.org/#websocket>WebSocket</a></code>
  connection with a remote host, and so forth, <a href=workers.html#sharedworker id=broadcasting-to-other-browsing-contexts:sharedworker>shared workers</a> are
  the most appropriate solution.</p>

  <p>For simple cases, though, where a shared worker would be an unreasonable overhead, authors can
  use the simple channel-based broadcast mechanism described in this section.</p>

  

  <dl class=domintro><dt><code><var>broadcastChannel</var> = new <span id=dom-broadcastchannel>BroadcastChannel</span>(<var>name</var>)</code><dd>
    <p>Returns a new <code>BroadcastChannel</code> object via which messages for the given channel
    name can be sent and received.</p>
   <dt><code><var>broadcastChannel</var>.<span id=dom-broadcastchannel-name>name</span></code><dd><p>Returns the channel name (as passed to the constructor).<dt><code><var>broadcastChannel</var>.<span id=dom-broadcastchannel-postmessage>postMessage</span>(<var>message</var>)</code><dd>
    <p>Sends the given message to other <code>BroadcastChannel</code> objects set up for this
    channel. Messages can be structured objects, e.g. nested objects and arrays.</p>
   <dt><code><var>broadcastChannel</var>.<span id=dom-broadcastchannel-close>close</span>()</code><dd><p>Closes the <code>BroadcastChannel</code> object, opening it up to garbage
   collection.</dl>

  

  <p class=note>Authors are strongly encouraged to explicitly close <code>BroadcastChannel</code>
  objects when they are no longer needed, so that they can be garbage collected. Creating many
  <code>BroadcastChannel</code> objects and discarding them while leaving them with an event
  listener and without closing them can lead to an apparent memory leak, since the objects will
  continue to live for as long as they have an event listener (or until their page or worker is
  closed).</p>

  

  <div class=example>

   <p>Suppose a page wants to know when the user logs out, even when the user does so from another
   tab at the same site:</p>

   <pre><code class='js'><c- a>var</c-> authChannel <c- o>=</c-> <c- k>new</c-> BroadcastChannel<c- p>(</c-><c- t>&apos;auth&apos;</c-><c- p>);</c->
authChannel<c- p>.</c->onmessage <c- o>=</c-> <c- a>function</c-> <c- p>(</c->event<c- p>)</c-> <c- p>{</c->
  <c- k>if</c-> <c- p>(</c->event<c- p>.</c->data <c- o>==</c-> <c- t>&apos;logout&apos;</c-><c- p>)</c->
    showLogout<c- p>();</c->
<c- p>}</c->

<c- a>function</c-> logoutRequested<c- p>()</c-> <c- p>{</c->
  <c- c1>// called when the user asks us to log them out</c->
  doLogout<c- p>();</c->
  showLogout<c- p>();</c->
  authChannel<c- p>.</c->postMessage<c- p>(</c-><c- t>&apos;logout&apos;</c-><c- p>);</c->
<c- p>}</c->

<c- a>function</c-> doLogout<c- p>()</c-> <c- p>{</c->
  <c- c1>// actually log the user out (e.g. clearing cookies)</c->
  <c- c1>// ...</c->
<c- p>}</c->

<c- a>function</c-> showLogout<c- p>()</c-> <c- p>{</c->
  <c- c1>// update the UI to indicate we&apos;re logged out</c->
  <c- c1>// ...</c->
<c- p>}</c-></code></pre>

  </div>



  <nav><a href=server-sent-events.html>← 9.2 Server-sent events</a> — <a href=index.html>Table of Contents</a> — <a href=workers.html>10 Web workers →</a></nav>
